#region Released to Public Domain by Gael Fraiteur
/*----------------------------------------------------------------------------*
 *   This file is part of samples of PostSharp.                                *
 *                                                                             *
 *   This sample is free software: you have an unlimited right to              *
 *   redistribute it and/or modify it.                                         *
 *                                                                             *
 *   This sample is distributed in the hope that it will be useful,            *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                      *
 *                                                                             *
 *----------------------------------------------------------------------------*/
#endregion

using System;
using System.Reflection;
using PostSharp.Laos;

namespace PostSharp.Samples.Librarian.Framework
{
    /// <summary>
    /// Base class for field validation custom attributes.
    /// </summary>
    [Serializable]
    public abstract class FieldValidationAttribute : OnFieldAccessAspect, ILaosReflectionAspectProvider
    {
        private string fieldName;

        [NonSerialized] private FieldInfo field;

        protected string FieldName { get { return this.fieldName; } }

        internal FieldInfo TargetField { get { return this.field; } }

        /// <summary>
        /// Called at compile-time to initialize the current instance.
        /// </summary>
        /// <param name="field">Field to which the current custom attribute is applied.</param>
        public override void CompileTimeInitialize( FieldInfo field )
        {
            base.CompileTimeInitialize( field );
            this.field = field;
            this.fieldName = field.DeclaringType.Name + "." + field.Name;
        }


        /// <summary>
        /// Called at runtime whenever one modifies the field to which the current custom attribute is applied.
        /// </summary>
        /// <param name="eventArgs">Event arguments.</param>
        public override void OnSetValue( FieldAccessEventArgs eventArgs )
        {
            this.ValidateFieldValue( eventArgs.ExposedFieldValue );
            base.OnSetValue( eventArgs );
        }


        /// <summary>
        /// When implemented by a derived class, validates a value.
        /// </summary>
        /// <param name="value">The field value.</param>
        public abstract void ValidateFieldValue( object value );


        /// <summary>
        /// Provides the aspect for the code generation of the <see cref="Aspectable.AutoGeneratedValidate"/>
        /// method.
        /// </summary>
        /// <param name="collection">Collection to which the aspect has to be added.</param>
        void ILaosReflectionAspectProvider.ProvideAspects( LaosReflectionAspectCollection collection )
        {
            TypeValidationAspect.RegisterFieldValidator( this.field, this, collection );
        }

    }
}